# -*- coding: utf-8 -*-
"""
@Time : 2024/10/17 18:24
@Author : ChenXiaoliang
@Email : middlegod@sina.com
@File : monitor_app.py
"""
import json
import logging
import threading
import time
import requests

from monitor_tasks.get_newest_consume_coupon import get_consume_coupon_info
from monitor_tasks.monitor_weibo_user import get_userid_by_name, get_mblog, get_mblog_long_text
from monitor_tasks.weibo_search import get_weibo_search
from monitor_tasks.monitor_toutiao_user import get_toutiao_user_content
from monitor_tasks.get_daily_funds_ranks import get_daily_funds_ranks
from sys_func.file_relation import if_saved_in_file, saved_to_file
from sys_func.read_config import load_yaml
from sys_func.send_email import send_email

LOG_FORMAT = "%(levelname)s %(asctime)s - %(message)s"
logging.basicConfig(filename='monitor.log', level=logging.INFO, filemode='a', format=LOG_FORMAT)
logger = logging.getLogger()


def get_sub_cookie():
    session = requests.Session()
    session_url = """
        https://login.sina.com.cn/visitor/visitor?a=crossdomain&s=_2AkMeUW2sdcPxrAJZmv8WyWvhaolH-jythARaAn7uJhMyOhh87goXqSdutBF-XKZoH7j4qHcFNgZse15cS9tih-UG&sp=0033WrSXqPxfM72wWs9jqgMF55529P9D9WFmpDoV36wskXrwCOfoDO7o5JpVhsfD9sxj9gUa9FR3Zntt&from=weibo&_rand=0.5841943882049672&entry=miniblog&url=https%3A%2F%2Fweibo.com%2Flogin.php%3Furl%3Dhttps%253A%252F%252Fweibo.com%252Fnewlogin%253Ftabtype%253Dlist%2526gid%253D1028039999%2526openLoginLayer%253D0%2526url%253Dhttps%25253A%25252F%25252Fweibo.com%25252F
        """
    session.get(session_url, headers={"referer": "https://passport.weibo.com/",
                                      "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"})
    cookie_sub = session.cookies.get_dict().get("SUB")
    logger.info(f"获取到的cookie信息sub值：{cookie_sub}")
    if len(cookie_sub) >= 10:
        sub_info = "SUB=" + cookie_sub + ";"
    else:
        # 获取配置文件中的页数配置值
        config_data = load_yaml('config_monitor.yaml')
        sub_info = config_data.get('weibo').get('cookie_sub')
    return sub_info


def get_funds_ranks_job():
    while True:
        logger.info("开始执行每日一次的基金排序统计任务")
        result = get_daily_funds_ranks()
        body = """<html>
                                              <body>"""
        for funds in result:
            body += f"""<h3 style="text-align:center;">不同时间范围内的基金排序</h3>"""

            part_body = "<table>"
            tr_th_html_str = "<tr>"
            for column in funds:
                tr_th_html_str += f"<th>{column}</th>"
            tr_th_html_str += "</tr>"
            part_body += tr_th_html_str

            tr_td_html_str = ""
            for fund in funds.values:
                tr_td_html_str += "<tr>"
                for info in fund:
                    if fund.tolist().index(info) == 0:
                        tr_td_html_str += f"""<td><a href="https://gushitong.baidu.com/fund/ab-{info}">{info}</a></td>"""
                    else:
                        tr_td_html_str += f"<td>{info}</td>"
                tr_td_html_str += "</tr>"
            part_body += tr_td_html_str

            part_body += "</table>"

            body += part_body

        body = body + """</body>
                                        </html>"""

        send_email(f"Funds Rank {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}",
                   body, 'html')
        logger.info("完成执行每日一次的基金排序统计任务，并已成功发送邮件")
        # 等待24小时后继续执行
        time.sleep(60 * 24 * 60)


def monitor_toutiao_user_job():
    while True:
        logger.info("&&&开始监控头条用户内容&&&")
        toutiao_content_info = get_toutiao_user_content()
        logger.info(f"monitor_app.py脚本中获取到的{toutiao_content_info}")
        if toutiao_content_info:
            # 成功获取到内容
            toutiao_content_file = "toutiao_content_record.txt"
            logger.info(f"monitor_app.py脚本中获取到的头条内容：{toutiao_content_info.get('content')}")
            if not if_saved_in_file(toutiao_content_info.get('content'), toutiao_content_file):
                # 邮件正文内容编辑
                content = f"""
                            <html>
                              <body>
                                <h1><a href="{toutiao_content_info.get('url')}" style="text-decoration: none;">{toutiao_content_info.get('content')}</a></h1>
                                <p>发布于 {toutiao_content_info.get('p_time')} from {toutiao_content_info.get('location', '发布地址获取失败')}</p>
                              </body>
                            </html>
                            """
                # 发送邮件
                send_result = send_email(
                    f"头条用户“炒股的人枣庄薛城股民”的最新头条内容! —— {time.strftime('%H:%M:%S', time.localtime())}",
                    content, "html")
                # 发送邮件成功后，对其记录之，保存news_title
                if send_result:
                    saved_to_file(toutiao_content_info.get('content'), toutiao_content_file)
        else:
            send_email(f"头条用户内容获取失败！{time.strftime('%H:%M:%S', time.localtime())}",
                       "<html><body><p>头条用户内容获取失败，请及时处理！</p></body></html>", "html")
        logger.info("&&&结束监控头条用户内容&&&")
        # 监控时间间隔
        gap_time = load_yaml('config_monitor.yaml').get('monitor_toutiao_user_gap')
        time.sleep(60 * gap_time)


def consume_coupon_job():
    while True:
        """监控最新消费券功能部分"""
        logger.info("+++开始监控最新消费券功能+++")
        r_consume_coupon_info = get_consume_coupon_info()
        if not r_consume_coupon_info:
            # 如果返回的是空，即获取消费券信息失败
            logger.error("获取最新消费券信息失败，等待下一次请求")
        else:
            news_title, news_href, news_brief, news_p_time, news_source = r_consume_coupon_info
            logger.info(news_title)
            consume_coupon_file = 'consume_coupon_record.txt'
            if not if_saved_in_file(news_title, consume_coupon_file):
                # 邮件正文内容
                content = f"""
                                <html>
                                  <body>
                                    <h1><a href="{news_href}" style="text-decoration: none;">{news_title}</a></h1>
                                    <p>{news_brief}</p>
                                    <p>发布于 {news_p_time} from {news_source}</p>
                                  </body>
                                </html>
                                """
                # 发送邮件
                send_result = send_email(f"最新的消费券消息 —— {news_title}", content, "html")
                # 发送邮件成功后，对其记录之，保存news_title
                if send_result and news_title != "获取消费券报错，请及时去处理":
                    saved_to_file(news_title, consume_coupon_file)
        logger.info("+++结束监控最新消费券功能+++")
        # 监控时间间隔
        gap_time = load_yaml('config_monitor.yaml').get('consume_gap')
        time.sleep(60 * gap_time)


def weibo_search_job():
    while True:
        """微博图片搜索功能部分"""
        logger.info("***开始微博搜索功能***")
        config_data = load_yaml('config_monitor.yaml')

        body = """<html>
                                      <body>"""

        kw_list = config_data.get('weibo').get("search").get("kw")
        # 记录微博查询博文的记录文件
        record_file = 'search_blog_record.txt'
        for kw in kw_list:
            results = get_weibo_search(kw)
            if results:

                # 判断第一个是否已经被记录，如果记录，退出邮件正文内容的编辑。
                # 即退出该次关键字的查询，进入下一个关键字的查询
                first_result = results[0]
                first_result_context = first_result.get('title')
                if if_saved_in_file(first_result_context, record_file):
                    continue

                body += f"""<h3 style="text-align:center;">{kw} weibo search result</h3>"""
                for result in results:

                    blog_context = result.get('title')
                    # 是否已存在于记录文件中，如果是退出循环。
                    # 逻辑：如果这一条已记录，后面的都已经被记录在文件中了。 这条逻辑是错误的
                    # 可能有不同用户编辑了相同的内容，如果这样，后面再跟有不同内容也不会在邮件正文中编辑了
                    # 所以不能用break ，修改为continue
                    if if_saved_in_file(blog_context, record_file):
                        continue

                    # 把博文存到查询记录文件中
                    saved_to_file(blog_context, record_file)

                    part_body = f"""
                            <div style="border: 1px solid black;">
                            <h5>{result.get('title')}</h5>
                            <p>发布于 {result.get('created_at')} from 【{result.get('user_name')}】 {result.get('user_url')}</p>
                            </div>
                            """
                    body += part_body

        body = body + """</body>
                        </html>"""

        # logger.info(f"完整的微博搜索邮件正文内容html：\n{body}")
        # 如果不存在‘div’表名是一个空的html，只进行日志提醒，不发送邮件！
        if "div" not in body:
            logger.info("所有的搜索结果均未有最新内容，不发邮件！")
        # 如果存在‘div’，说明html有新内容，需发送邮件！
        else:
            # 发送邮件
            send_email(f"weibo search result at {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}",
                       body, 'html')
        logger.info("***结束微博搜索功能***")

        # 监控时间间隔
        gap_time = load_yaml('config_monitor.yaml').get('weibo_search_gap')
        time.sleep(60 * gap_time)


def monitor_weibo_user_job():
    while True:
        # 获取sub值
        sub_info = get_sub_cookie()
        """monitor weibo user section"""
        logger.info("$$$开始监控weibo user mblog$$$")
        targets = load_yaml('config_monitor.yaml').get('weibo').get('monitor_user')
        # 保存初始数据
        temp = []
        for target in targets:
            with open('weibo_user.json', 'r') as f:
                users = json.load(f)
            if target not in users:
                try:
                    u_id = get_userid_by_name(target, sub_info)
                    users[target] = u_id
                except Exception as e:
                    logger.error(f"获取用户id的过程中报错：{e}，放弃用户{target}博文的抓取！")
                    continue
                with open('weibo_user.json', 'w') as f:
                    json.dump(users, f, ensure_ascii=False)
            else:
                u_id = users[target]
            u_blogs = get_mblog(u_id, 1, sub_info)
            if not u_blogs:
                # 为空
                break
            u_1st_blog = u_blogs[0]
            # 获取是否是长文微博
            is_long_text = u_1st_blog.get('is_long_text')
            logger.info(f"对用户{target}获取到的第一条微博是否是长博文：{is_long_text}")
            if is_long_text:
                # 如果是长博文，需要点击展开获取完整内容
                # 获得微博博文id
                mblog_id = u_1st_blog.get('mblogid')
                logger.info(f"对用户{target}获取到的第一条微博id是：{mblog_id}")
                u_1st_blog_text = get_mblog_long_text(u_id, mblog_id, sub_info)
                u_1st_blog['text'] = u_1st_blog_text
            else:
                # 如果不是长博文
                u_1st_blog_text = u_1st_blog['text']
            # 判断是否已存在于记录的最新mblog文本文件中，即是否之前邮件已发送过，期间用户未在更新最新mblog
            save_newest_blog_file = 'user_blog_record.txt'
            if if_saved_in_file(u_1st_blog_text, save_newest_blog_file):
                continue

            u_1st_blog['user'] = target
            u_1st_blog['user_url'] = f"https://weibo.com/u/{u_id}"
            temp.append(u_1st_blog)
            # 保存用户的最新mblog至monitor_blog.txt文本文件中
            saved_to_file(u_1st_blog_text, save_newest_blog_file)

        if temp:
            # 处理初始数据，排版
            email_body = """<html>
                                          <body>"""

            for mblog in temp:
                part_html = f"""
                                    <div style="border: 1px solid black;">
                                    <h5>{mblog.get('text')}</h5>
                                    <p>from 【{mblog.get('user')}】{mblog.get('user_url')}</p>
                                    <p>{mblog.get('address_site') if mblog.get('address_site') else "无发布地点信息"} at {mblog.get('publish_time')}</p>
                                    </div>
                                    """
                email_body += part_html

            email_body = email_body + """</body>
                                        </html>"""

            send_email(f"monitor weibo users blog {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}", email_body,
                       'html')
        else:
            logger.info("监控的全部用户在监控周期内均暂未更新微博或者cookie已失效需要及时替换处理，不发送邮件！")
        logger.info("$$$结束监控weibo user mblog$$$")

        # 监控时间间隔
        gap_time = load_yaml('config_monitor.yaml').get('monitor_weibo_user_gap')
        time.sleep(60 * gap_time)


if __name__ == '__main__':
    # 创建监控任务线程
    thread_1 = threading.Thread(target=consume_coupon_job)
    thread_2 = threading.Thread(target=weibo_search_job)
    thread_3 = threading.Thread(target=monitor_weibo_user_job)
    thread_4 = threading.Thread(target=monitor_toutiao_user_job)
    thread_5 = threading.Thread(target=get_funds_ranks_job)

    # 启动线程
    thread_1.start()
    thread_2.start()
    thread_3.start()
    thread_4.start()
    thread_5.start()
